package main

import (
	"flag"
	"fmt"
	"github.com/Unknwon/goconfig"
	"github.com/syyongx/php2go"
	"hello/wl"
	"net"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

var port int
var portRange string

var parallelCounts int

var CH  [] chan bool
var CHA   chan int
var err error

var Conf map[string] map[string]string

func init() {

	flag.IntVar(&port, "p", 80, "port")
	flag.StringVar(&portRange, "r", "", "range ports. format is <from>~<to>. eg. 100~200")
	flag.IntVar(&parallelCounts, "n", 1, "parallel counts")

	// 修改提示信息
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "\nUsage: %s [Options] <IP>\n\nOptions:\n\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.Parse()

}

func printOpeningPort(port int) {

	fmt.Println("port " + strconv.Itoa(port) + " is opening")

}

func checkPort(ip net.IP, port int, wg *sync.WaitGroup, parallelChan *chan int) {

	defer wg.Done()

	tcpAddr := net.TCPAddr{
		IP:   ip,
		Port: port,
	}

	conn, err := net.DialTCP("tcp", nil, &tcpAddr)

	if err == nil {
		printOpeningPort(port)
		conn.Close()

	}

	<-*parallelChan

}

func check(ip net.IP, port int,ch chan bool) {
	tcpAddr := net.TCPAddr{
		IP:   ip,
		Port: port,
	}

	conn, err := net.DialTCP("tcp", nil, &tcpAddr)



	if err == nil {

		printOpeningPort(port)
		conn.Close()
		ch <- true;
		//return true
	}else{
		fmt.Println("没有连接")
		ch <- false;
		//return  false;
	}

	//conn.CloseRead()
	//conn.CloseWrite()

}

func main() {
	CH=make([] chan bool, 10)

	for i:=0;i<10 ;i++{
		CH[i]=make(chan bool)
	}

	loadINI()


	mysqlIp:=net.ParseIP(Conf["mysql"]["ip"])
	mysqlPort:=wl.ToInt(Conf["mysql"]["port"])

	redisIp:=net.ParseIP(Conf["redis"]["ip"])
	redisPort:=wl.ToInt(Conf["redis"]["port"])

	ApacheIp:=net.ParseIP(Conf["http"]["ip"])
	ApachePort:=wl.ToInt(Conf["http"]["port"])


	TimeCount:=wl.ToInt64(Conf["Time"]["count"])

	//args := flag.Args()
	//ip := net.ParseIP(flag.Arg(0))
	//port :=wl.ToInt(flag.Arg(1))
	CHA = make(chan int)

	for {
		//break
		//if  check(ip, port) ==true {
		//	fmt.Println("连接成功!")
		//}else{
		//
		//}

		go  check(mysqlIp, mysqlPort,CH[0])
		go  check(redisIp, redisPort,CH[1])
		go  check(ApacheIp, ApachePort,CH[2])



		temp1:=<-CH[0]
		temp2:=<-CH[1]
		temp3:=<-CH[2]
		fmt.Println("Mysql读取结果",temp1)
		fmt.Println("Redis读取结果",temp2)
		fmt.Println("Apache读取结果",temp3)

		//select {
		//case temp:=<- CHA:
		//	// 如果chan1成功读到数据
		//	fmt.Println("读取结果",temp)
		//
		//
		//default:
		//	// 默认分支
		//	fmt.Println("失败!??")
		//}

		php2go.Sleep(TimeCount);

	}



}

func loadINI()  {
	Conf=make(map[string]map[string]string)
	cfg, _ := goconfig.LoadConfigFile("conf.conf")


	RedisSec, err := cfg.GetSection("Redis")
	MysqlSec, err := cfg.GetSection("Mysql")
	HttpdSec, err := cfg.GetSection("HttpServer")
	Time, err := cfg.GetSection("Time")


	if err!=nil {
		fmt.Println(err)
	}
	Conf["redis"]=RedisSec
	Conf["mysql"]=MysqlSec
	Conf["http"]=HttpdSec
	Conf["Time"]=Time

	fmt.Println(Conf)
	fmt.Println(Conf["redis"]["ip"])


}

func test(){
	args := flag.Args()

	if len(args) != 1 {
		flag.Usage()
	} else {

		ip := net.ParseIP(flag.Arg(0))

		// 用于协程任务控制
		wg := sync.WaitGroup{}

		if portRange != "" {

			matched, _ := regexp.Match(`^\d+~\d+$`, []byte(portRange))

			if !matched {

				flag.Usage()

			} else {

				portSecs := strings.Split(portRange, "~")

				startPort, err1 := strconv.Atoi(portSecs[0])
				endPort, err2 := strconv.Atoi(portSecs[1])

				if err1 != nil || err2 != nil || startPort < 1 || endPort < 2 || endPort <= startPort || parallelCounts < 1 {
					flag.Usage()
				} else {

					wg.Add(endPort - startPort + 1)

					// 用于控制协程数
					parallelChan := make(chan int, parallelCounts)

					for i := startPort; i <= endPort; i++ {

						parallelChan <- 1

						go checkPort(ip, i, &wg, &parallelChan)

					}

					wg.Wait()

				}

			}

		} else {

			wg.Add(1)

			parallelChan := make(chan int)

			go func() {
				parallelChan <- 1
			}()

			go checkPort(ip, port, &wg, &parallelChan)

			wg.Wait()

		}

	}
}
